<?php
namespace zake\foundation\able\traits;

use zake\foundation\able\ProtocolAble;
use zake\foundation\stream\ReadStream;
use zake\helper\Console;


trait ReadTrait
{
    /**
     * read time
     * @var int
     */
    protected $readTime = 0;


    /**
     * read resource
     * @return resource
     *
     * @author liu.bin 2020-03-31 16:33
     */
    public function getReadResource()
    {
        return $this->getResource();
    }


    /**
     * read fd
     * @return int
     *
     * @author liu.bin 2020-04-28 15:05
     */
    public function getReadFd()
    {
        return $this->getFd();
    }


    /**
     * close read resource
     * @return bool
     *
     * @author liu.bin 2020-04-28 15:06
     */
    public function closeReadResource()
    {
        if(!$this->isCloseReadResource()){
            return $this->closeResource();
        }
        return true;
    }


    /**
     * read resource close
     * @return bool
     *
     * @author liu.bin 2020-04-28 15:10
     */
    public function isCloseReadResource()
    {
        return $this->isCloseResource();
    }


    /**
     * 设定读取时间
     * 时间戳，秒
     *
     * @param int|null $time
     * @author liu.bin 2020-03-31 16:43
     */
    public function setReadTime($time = null)
    {
        $this->readTime = is_null($time)? time() : $time;
    }


    /**
     * 获取上一次接收数据的时间,秒
     *
     * @return int
     * @author liu.bin 2020-03-28 21:18
     */
    public function getReadTime()
    {
        if(is_null($this->readTime)){
            $this->readTime = time();
        }
        return $this->readTime;
    }


    /**
     * 同步阻塞读取数据
     *
     * 按协议读取
     * @param null|ProtocolAble $protocol
     * @param null|\Closure $closeCallback
     * @param string $buffer 缓冲区字符串
     *
     * @return bool|string
     *
     * @author liu.bin 2020-05-19 15:49
     */
    public function read(ProtocolAble $protocol,$closeCallback = null,$buffer = "")
    {

        // 读取当前数据流（不清空socket）
        $readBuffer = $this->readOnce(ReadStream::READ_MAX_LENGTH,STREAM_PEEK);

        if(empty($readBuffer)){
            $this->close($closeCallback);
            return false;
        }

        //
        $buffer = $buffer.$readBuffer;
        $bufferLen = strlen($buffer);

        // 校验当前数据字节长度
        if($bufferLen > ReadStream::FRAME_MAX_LENGTH){
            $this->close($closeCallback);
            return false;
        }

        // 获取当前协议的数据字节长度
        $frameLength = $protocol->framePoint($buffer,$this);
        if(false === $frameLength){
            $this->close($closeCallback);
            return false;
        }

        // 读取缓冲区数据
        if($frameLength){
            if($this->getFd() > 2){
                return $this->readOnce($frameLength);
            }else{
                // 兼容终端输入的数据
                return $buffer;
            }
        }


        // 如果有数据，则递归（阻塞）读取
        return $this->read($protocol,$closeCallback,$buffer);
    }


    /**
     * 从socket中读取数据流
     *
     * @param int $length 读取数据流长度
     * @param null|int 读取模式
     *
     * @return string
     *
     * @author liu.bin 2020-05-19 15:39
     */
    protected function readOnce($length=ReadStream::READ_MAX_LENGTH,$flag = null)
    {
        $resource = $this->getReadResource();
        if(empty($resource)){
            return false;
        }
        $this->setReadTime();

        $fd = $this->getFd();
        if($fd > 2){
            $buffer = stream_socket_recvfrom($resource,$length,$flag);
        }else{
            $buffer = fread($resource,$length);
        }

        return $buffer;

    }
}